using System;
using System.Linq.Expressions;

namespace Ioc.Kernel.LifeStyles
{
    public class SingletonLifeStyleStrategy : DefaultLifeStyleStrategy
    {
        private static readonly object syncObj = new object();
        private static object instance;

        /// <summary>
        /// Musts the instanciate.
        /// </summary>
        /// <returns></returns>
        public override bool MustInstanciate()
        {
            lock (syncObj)
            {
                return instance == null;
            }
        }

        /// <summary>
        /// Gets the expression.
        /// </summary>
        /// <returns></returns>
        public override Expression GetExpression(Type className)
        {
            return Expression.Constant(Convert.ChangeType(instance, className));
        }

        /// <summary>
        /// Sets the expression.
        /// </summary>
        /// <param name="expression">The expression.</param>
        public override void SetExpression(Expression expression)
        {
            lock (syncObj)
            {
                if (instance != null) return;

                var func = Expression.Lambda<Func<object>>(expression).Compile();
                instance = func();
            }
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        public override void Dispose(bool disposing)
        {
            if(!disposing) return;
            instance = null;
        }
    }
}